#include "glShader.h"

#include <stdio.h>
#include <string.h>

#pragma warning(disable: 4996)

CglShader::CglShader(void){}

CglShader::~CglShader(void) { Delete(); }

bool CglShader::Create(char *pStr, GLenum type, GLenum gsIn, GLenum gsOut)
{
    m_ID = glCreateShader(type);

    size_t slen = strlen(pStr);
    glShaderSource( m_ID, 1, (const GLchar **) &pStr, (GLint *)&slen);

    glCompileShader(m_ID);

    int32 result = 0;
    glGetObjectParameterivARB(m_ID, GL_OBJECT_COMPILE_STATUS_ARB, &result);  

    if (result)
    {
        switch (type)
        {
            case GL_VERTEX_SHADER:
                sprintf(m_Log, "Vertex shader loaded successfully");
            break;
            case GL_FRAGMENT_SHADER:
                sprintf(m_Log, "Fragment shader loaded successfully");
            break;
            case GL_GEOMETRY_SHADER_EXT:
                glProgramParameteriEXT(m_ID, GL_GEOMETRY_INPUT_TYPE_EXT,  gsIn);
                glProgramParameteriEXT(m_ID, GL_GEOMETRY_OUTPUT_TYPE_EXT, gsOut); 
                glProgramParameteriEXT(m_ID, GL_GEOMETRY_VERTICES_OUT_EXT, 4); 
                
                sprintf(m_Log, "Geometry shader loaded successfully");
            break;
        }
    }
    else
    {
        glGetInfoLogARB(m_ID, 1024, &m_LogLength, m_Log);
        fprintf(stderr, "%s \n", m_Log);
    }

    return (result ? true : false);
}

bool CglShader::CreateFromFile(char *fname, GLenum type, GLenum gsIn, GLenum gsOut)
{
    char * pStr = NULL;
    FILE *pFile = fopen(fname, "rb");

    m_ID = 0;

    if (pFile == NULL) 
        return false;

    // obtain file size:
    fseek(pFile, 0, SEEK_END);
    int fsize = ftell (pFile);
    fseek(pFile, 0 , SEEK_SET);

    // allocate memory to contain the whole file:
    pStr = (char*) malloc (sizeof(char)*fsize+1);
    if (pStr == NULL) 
        return false;

    // copy the file into the buffer:
    size_t nread = fread (pStr, 1, fsize, pFile);
    if (nread != fsize) 
        return false;

    fclose(pFile);

    pStr[fsize] = 0;

    bool result = Create(pStr, type, gsIn, gsOut);
    
    if (result)
    {
        switch (type)
        {
            case GL_VERTEX_SHADER:
                sprintf(m_Log, "Vertex shader %s loaded successfully", fname);
            break;
            case GL_FRAGMENT_SHADER:
                sprintf(m_Log, "Fragment shader %s loaded successfully", fname);
            break;
        }
    }
    else
        glGetInfoLogARB(m_ID, 1024, &m_LogLength, m_Log);

    return result;
}

void CglShader::Delete()
{
    glDeleteObjectARB(m_ID);
}